<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>es5普通对象的原型</title>
  <!-- 
  在JavaScript中，ES5（ECMAScript 5）引入了一些新的特性和方法来增强对象的功能。普通对象的原型是理解JavaScript对象继承和原型链的关键。
  一、普通对象的定义
  普通对象是由键值对组成的无序集合，键是字符串（或符号），值可以是任意类型的值（包括其他对象、数组、函数等）。在JavaScript中，所有对象都是从  `Object`  构造函数继承而来的。

  二、原型链
  1. 原型（Prototype）：
    - 每个JavaScript对象都有一个内部属性 `[[Prototype]]` ，指向别的原型对象。
    - 通过原型，对象可以继承其他对象的属性和方法。

  2. 原型链（Prototype Chain）：
    - 当访问对象的属性或方法时，如果该对象没有该属性或方法，JavaScript会沿着原型链向上查找，直到找到该属性或方法，或者到达原型链的顶端（ `null` ）。

  三、创建普通对象的方式
  1. 字面量方式：
    - 使用对象字面量创建对象。
    const obj = {
        name: 'Alice',
        age: 25,
        greet: function() {
            console.log('Hello, ' + this.name);
        }
    };
  2. 构造函数方式：
    - 使用  `function`  定义构造函数，并通过  `new`  关键字创建对象。
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }

    Person.prototype.greet = function() {
        console.log('Hello, ' + this.name);
    };

    const person1 = new Person('Bob', 30);

  四、原型的使用
  1. 添加方法到原型：
    - 可以通过  `prototype`  属性为构造函数添加方法，这样所有通过该构造函数创建的对象实例都可以访问这些方法。
    Person.prototype.sayAge = function() {
        console.log('I am ' + this.age + ' years old.');
    };

    person1.sayAge(); // 输出: I am 30 years old.
  2. 查找原型属性：
    - 访问对象的属性时，JavaScript会首先查找对象自身的属性，如果没有找到，则会查找其原型。
    console.log(person1.greet()); // 输出: Hello, Bob

  五、原型的优先级
  - 当访问对象的属性时，JavaScript会优先查找对象自身的属性，如果对象自身没有该属性，则会沿着原型链查找。
  - 如果在原型中定义了属性或方法，所有实例都可以共享这些属性和方法，从而节省内存。

  六、总结
  - ES5中的普通对象通过原型链实现了继承和共享。
  - 可以通过字面量或构造函数创建对象，并通过原型为对象添加方法。
  - 原型链的机制使得对象可以继承其他对象的属性和方法，这是JavaScript实现面向对象编程的重要特性。
   -->
</head>

<body>

  <script>
    // 1. 字面量方式：
    const person1 = {
      name: 'Bob',
      age: 30,
      greet: function () {
        console.log('Hello, ' + this.name);
      }
    };

    console.log(person1);

    // 获取对象的原型：
    console.log("获取对象的原型：", person1.name, person1.age, person1.greet);
    console.log("获取对象的原型：", Object.getPrototypeOf(person1));
    console.log("获取对象的原型：", person1.__proto__);
    console.log("获取对象的原型：", Object.getPrototypeOf(person1) === Object.prototype);
    console.log("获取对象的原型：", person1.__proto__ === Object.prototype);
    
    // 2. 疑问: 这个原型有什么用呢?
    // 当我们通过[[get]]方式获取一个属性对应的value时
    // 1> 它会优先在自己的对象中查找, 如果找到直接返回
    // 2> 如果没有找到, 那么会在原型对象中查找, 如果找到直接返回
    // 3> 如果原型对象中也没有找到, 那么会继续沿着原型链查找, 直到找到Object.prototype为止
    // 4> 如果还是没有找到, 那么返回undefined
    person1.__proto__.message = "Hello World";
    console.log(person1.message);
    console.log(person1);
    
    
    
    



  </script>

</body>

</html>